package com.erlang4j.api;

import com.ericsson.otp.erlang.OtpErlangObject;

/**
 * <p>
 * Represents a binding between strings and OtpErlangObjects. It is used
 * <ul>
 * <li>To help with pattern matching: if a value is present in the binding, then the pattern only matches if the value
 * is the same
 * <li>To give the result from pattern matching
 * <li>To give the value of variables when composing Erlang objects from patterns
 * </ul>
 * </p>
 * <p>
 * Design notes:
 * <ul>
 * <li>This is an immutable interface. To make a new one you use bind which returns a new binding with the new extra
 * data
 * <li>The "isValid()" is a topic under discussion. Should an invalid binding (representing the fact that the binding
 * has failed) be an Ibinding? Should we throw an exception? Having tried the code both ways, the usage of the code is
 * nicer this way.
 * </ul>
 * </p>
 * 
 * @author Phil Rice
 */
public interface IBinding extends IGetData {
	/**
	 * Makes an invalid binding, or a new binding with the same values as this one, plus an extra binding from key ->
	 * object.
	 * 
	 * @param key
	 *            the string that will be the name of the bound object
	 * @param object
	 *            the bound object
	 * @return a new binding with either: <br>
	 *         all the old bindings plus a map from key to value<br>
	 *         or no bindings, and its invalid if the key is already mapped to a different object
	 */
	IBinding bind(String key, OtpErlangObject object);

	/** This is like bind except that it allows a key that already exists to be bound to a different object */
	IBinding bindAllowingChange(String key, OtpErlangObject object);

	/** The binding might not be valid if this is the result of pattern matching */
	boolean isValid();

	/** Produces a new binding which is the merge of the two */
	IBinding merge(IBinding bindings);
}
